home *** CD-ROM | disk | FTP | other *** search
/ CD Actual Thematic 7: Programming / CDAT7.iso / Share / Codigo / hh / rsource.exe / Hexen Source / R_THINGS.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-03-22  |  21.5 KB  |  1,034 lines

  1.  
  2. //**************************************************************************
  3. //**
  4. //** r_things.c : Heretic 2 : Raven Software, Corp.
  5. //**
  6. //** $RCSfile: r_things.c,v $
  7. //** $Revision: 1.26 $
  8. //** $Date: 96/01/06 18:37:42 $
  9. //** $Author: bgokey $
  10. //**
  11. //**************************************************************************
  12.  
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include "h2def.h"
  16. #include "r_local.h"
  17.  
  18. void R_DrawColumn (void);
  19. void R_DrawFuzzColumn (void);
  20. void R_DrawAltFuzzColumn(void);
  21. //void R_DrawTranslatedAltFuzzColumn(void);
  22.  
  23. typedef struct
  24. {
  25.     int        x1, x2;
  26.  
  27.     int        column;
  28.     int        topclip;
  29.     int        bottomclip;
  30. } maskdraw_t;
  31.  
  32. /*
  33.  
  34. Sprite rotation 0 is facing the viewer, rotation 1 is one angle turn CLOCKWISE around the axis.
  35. This is not the same as the angle, which increases counter clockwise
  36. (protractor).  There was a lot of stuff grabbed wrong, so I changed it...
  37.  
  38. */
  39.  
  40.  
  41. fixed_t        pspritescale, pspriteiscale;
  42.  
  43. lighttable_t    **spritelights;
  44.  
  45. // constant arrays used for psprite clipping and initializing clipping
  46. short    negonearray[SCREENWIDTH];
  47. short    screenheightarray[SCREENWIDTH];
  48.  
  49. boolean LevelUseFullBright;
  50. /*
  51. ===============================================================================
  52.  
  53.                         INITIALIZATION FUNCTIONS
  54.  
  55. ===============================================================================
  56. */
  57.  
  58. // variables used to look up and range check thing_t sprites patches
  59. spritedef_t        *sprites;
  60. int                numsprites;
  61.  
  62. spriteframe_t    sprtemp[30];
  63. int                maxframe;
  64. char            *spritename;
  65.  
  66.  
  67.  
  68. /*
  69. =================
  70. =
  71. = R_InstallSpriteLump
  72. =
  73. = Local function for R_InitSprites
  74. =================
  75. */
  76.  
  77. void R_InstallSpriteLump (int lump, unsigned frame, unsigned rotation, boolean flipped)
  78. {
  79.     int        r;
  80.  
  81.     if (frame >= 30 || rotation > 8)
  82.         I_Error ("R_InstallSpriteLump: Bad frame characters in lump %i", lump);
  83.  
  84.     if ((int)frame > maxframe)
  85.         maxframe = frame;
  86.  
  87.     if (rotation == 0)
  88.     {
  89. // the lump should be used for all rotations
  90.         if (sprtemp[frame].rotate == false)
  91.             I_Error ("R_InitSprites: Sprite %s frame %c has multip rot=0 lump"
  92.             , spritename, 'A'+frame);
  93.         if (sprtemp[frame].rotate == true)
  94.             I_Error ("R_InitSprites: Sprite %s frame %c has rotations and a rot=0 lump"
  95.             , spritename, 'A'+frame);
  96.  
  97.         sprtemp[frame].rotate = false;
  98.         for (r=0 ; r<8 ; r++)
  99.         {
  100.             sprtemp[frame].lump[r] = lump - firstspritelump;
  101.             sprtemp[frame].flip[r] = (byte)flipped;
  102.         }
  103.         return;
  104.     }
  105.  
  106. // the lump is only used for one rotation
  107.     if (sprtemp[frame].rotate == false)
  108.         I_Error ("R_InitSprites: Sprite %s frame %c has rotations and a rot=0 lump"
  109.         , spritename, 'A'+frame);
  110.  
  111.     sprtemp[frame].rotate = true;
  112.  
  113.     rotation--;        // make 0 based
  114.     if (sprtemp[frame].lump[rotation] != -1)
  115.         I_Error ("R_InitSprites: Sprite %s : %c : %c has two lumps mapped to it"
  116.         ,spritename, 'A'+frame, '1'+rotation);
  117.  
  118.     sprtemp[frame].lump[rotation] = lump - firstspritelump;
  119.     sprtemp[frame].flip[rotation] = (byte)flipped;
  120. }
  121.  
  122. /*
  123. =================
  124. =
  125. = R_InitSpriteDefs
  126. =
  127. = Pass a null terminated list of sprite names (4 chars exactly) to be used
  128. = Builds the sprite rotation matrixes to account for horizontally flipped
  129. = sprites.  Will report an error if the lumps are inconsistant
  130. =
  131. Only called at startup
  132. =
  133. = Sprite lump names are 4 characters for the actor, a letter for the frame,
  134. = and a number for the rotation, A sprite that is flippable will have an
  135. = additional letter/number appended.  The rotation character can be 0 to
  136. = signify no rotations
  137. =================
  138. */
  139.  
  140. void R_InitSpriteDefs (char **namelist)
  141. {
  142.     char        **check;
  143.     int        i, l, intname, frame, rotation;
  144.     int        start, end;
  145.  
  146. // count the number of sprite names
  147.     check = namelist;
  148.     while (*check != NULL)
  149.         check++;
  150.     numsprites = check-namelist;
  151.  
  152.     if (!numsprites)
  153.         return;
  154.  
  155.     sprites = Z_Malloc(numsprites *sizeof(*sprites), PU_STATIC, NULL);
  156.  
  157.     start = firstspritelump-1;
  158.     end = lastspritelump+1;
  159.  
  160. // scan all the lump names for each of the names, noting the highest
  161. // frame letter
  162. // Just compare 4 characters as ints
  163.     for (i=0 ; i<numsprites ; i++)
  164.     {
  165.         spritename = namelist[i];
  166.         memset (sprtemp,-1, sizeof(sprtemp));
  167.  
  168.         maxframe = -1;
  169.         intname = *(int *)namelist[i];
  170.  
  171.         //
  172.         // scan the lumps, filling in the frames for whatever is found
  173.         //
  174.         for (l=start+1 ; l<end ; l++)
  175.             if (*(int *)lumpinfo[l].name == intname)
  176.             {
  177.                 frame = lumpinfo[l].name[4] - 'A';
  178.                 rotation = lumpinfo[l].name[5] - '0';
  179.                 R_InstallSpriteLump (l, frame, rotation, false);
  180.                 if (lumpinfo[l].name[6])
  181.                 {
  182.                     frame = lumpinfo[l].name[6] - 'A';
  183.                     rotation = lumpinfo[l].name[7] - '0';
  184.                     R_InstallSpriteLump (l, frame, rotation, true);
  185.                 }
  186.             }
  187.  
  188.         //
  189.         // check the frames that were found for completeness
  190.         //
  191.         if (maxframe == -1)
  192.         {
  193.             //continue;
  194.             sprites[i].numframes = 0;
  195.             if (shareware)
  196.                 continue;
  197.             I_Error ("R_InitSprites: No lumps found for sprite %s"
  198.             ,namelist[i]);
  199.         }
  200.  
  201.         maxframe++;
  202.         for (frame = 0 ; frame < maxframe ; frame++)
  203.         {
  204.             switch ((int)sprtemp[frame].rotate)
  205.             {
  206.             case -1:    // no rotations were found for that frame at all
  207.                 I_Error ("R_InitSprites: No patches found for %s frame %c"
  208.                 , namelist[i], frame+'A');
  209.             case 0:    // only the first rotation is needed
  210.                 break;
  211.  
  212.             case 1:    // must have all 8 frames
  213.                 for (rotation=0 ; rotation<8 ; rotation++)
  214.                     if (sprtemp[frame].lump[rotation] == -1)
  215.                         I_Error ("R_InitSprites: Sprite %s frame %c is missing rotations"
  216.                         , namelist[i], frame+'A');
  217.             }
  218.         }
  219.  
  220.         //
  221.         // allocate space for the frames present and copy sprtemp to it
  222.         //
  223.         sprites[i].numframes = maxframe;
  224.         sprites[i].spriteframes =
  225.             Z_Malloc (maxframe * sizeof(spriteframe_t), PU_STATIC, NULL);
  226.         memcpy (sprites[i].spriteframes, sprtemp, maxframe*sizeof(spriteframe_t));
  227.     }
  228.  
  229. }
  230.  
  231.  
  232. /*
  233. ===============================================================================
  234.  
  235.                             GAME FUNCTIONS
  236.  
  237. ===============================================================================
  238. */
  239.  
  240. vissprite_t    vissprites[MAXVISSPRITES], *vissprite_p;
  241. int            newvissprite;
  242.  
  243.  
  244. /*
  245. ===================
  246. =
  247. = R_InitSprites
  248. =
  249. = Called at program start
  250. ===================
  251. */
  252.  
  253. void R_InitSprites (char **namelist)
  254. {
  255.     int        i;
  256.  
  257.     for (i=0 ; i<SCREENWIDTH ; i++)
  258.     {
  259.         negonearray[i] = -1;
  260.     }
  261.  
  262.     R_InitSpriteDefs (namelist);
  263. }
  264.  
  265.  
  266. /*
  267. ===================
  268. =
  269. = R_ClearSprites
  270. =
  271. = Called at frame start
  272. ===================
  273. */
  274.  
  275. void R_ClearSprites (void)
  276. {
  277.     vissprite_p = vissprites;
  278. }
  279.  
  280.  
  281. /*
  282. ===================
  283. =
  284. = R_NewVisSprite
  285. =
  286. ===================
  287. */
  288.  
  289. vissprite_t        overflowsprite;
  290.  
  291. vissprite_t *R_NewVisSprite (void)
  292. {
  293.     if (vissprite_p == &vissprites[MAXVISSPRITES])
  294.         return &overflowsprite;
  295.     vissprite_p++;
  296.     return vissprite_p-1;
  297. }
  298.  
  299.  
  300. /*
  301. ================
  302. =
  303. = R_DrawMaskedColumn
  304. =
  305. = Used for sprites and masked mid textures
  306. ================
  307. */
  308.  
  309. short        *mfloorclip;
  310. short        *mceilingclip;
  311. fixed_t        spryscale;
  312. fixed_t        sprtopscreen;
  313. fixed_t        sprbotscreen;
  314.  
  315. void R_DrawMaskedColumn (column_t *column, signed int baseclip)
  316. {
  317.     int        topscreen, bottomscreen;
  318.     fixed_t    basetexturemid;
  319.  
  320.     basetexturemid = dc_texturemid;
  321.  
  322.     for ( ; column->topdelta != 0xff ; )
  323.     {
  324. // calculate unclipped screen coordinates for post
  325.         topscreen = sprtopscreen + spryscale*column->topdelta;
  326.         bottomscreen = topscreen + spryscale*column->length;
  327.         dc_yl = (topscreen+FRACUNIT-1)>>FRACBITS;
  328.         dc_yh = (bottomscreen-1)>>FRACBITS;
  329.  
  330.         if (dc_yh >= mfloorclip[dc_x])
  331.             dc_yh = mfloorclip[dc_x]-1;
  332.         if (dc_yl <= mceilingclip[dc_x])
  333.             dc_yl = mceilingclip[dc_x]+1;
  334.  
  335.         if(dc_yh >= baseclip && baseclip != -1)
  336.             dc_yh = baseclip;
  337.  
  338.         if (dc_yl <= dc_yh)
  339.         {
  340.             dc_source = (byte *)column + 3;
  341.             dc_texturemid = basetexturemid - (column->topdelta<<FRACBITS);
  342. //            dc_source = (byte *)column + 3 - column->topdelta;
  343.             colfunc ();        // either R_DrawColumn or R_DrawFuzzColumn
  344.         }
  345.         column = (column_t *)(  (byte *)column + column->length + 4);
  346.     }
  347.  
  348.     dc_texturemid = basetexturemid;
  349. }
  350.  
  351.  
  352. /*
  353. ================
  354. =
  355. = R_DrawVisSprite
  356. =
  357. = mfloorclip and mceilingclip should also be set
  358. ================
  359. */
  360.  
  361. void R_DrawVisSprite (vissprite_t *vis, int x1, int x2)
  362. {
  363.     column_t    *column;
  364.     int            texturecolumn;
  365.     fixed_t        frac;
  366.     patch_t        *patch;
  367.     fixed_t        baseclip;
  368.  
  369.  
  370.     patch = W_CacheLumpNum(vis->patch+firstspritelump, PU_CACHE);
  371.  
  372.     dc_colormap = vis->colormap;
  373.  
  374. //    if(!dc_colormap)
  375. //        colfunc = fuzzcolfunc;    // NULL colormap = shadow draw
  376.  
  377.     if(vis->mobjflags&(MF_SHADOW|MF_ALTSHADOW))
  378.     {
  379.         if(vis->mobjflags&MF_TRANSLATION)
  380.         {
  381.             colfunc = R_DrawTranslatedFuzzColumn;
  382.             dc_translation = translationtables-256
  383.                 +vis->class*((MAXPLAYERS-1)*256)+
  384.                 ((vis->mobjflags&MF_TRANSLATION)>>(MF_TRANSSHIFT-8));
  385.         }
  386.         else if(vis->mobjflags&MF_SHADOW)
  387.         { // Draw using shadow column function
  388.             colfunc = fuzzcolfunc;
  389.         }
  390.         else
  391.         {
  392.             colfunc = R_DrawAltFuzzColumn;
  393.         }
  394.     }
  395.     else if(vis->mobjflags&MF_TRANSLATION)
  396.     {
  397.         // Draw using translated column function
  398.         colfunc = R_DrawTranslatedColumn;
  399.         dc_translation = translationtables-256
  400.             +vis->class*((MAXPLAYERS-1)*256)+
  401.             ((vis->mobjflags&MF_TRANSLATION)>>(MF_TRANSSHIFT-8));
  402.     }
  403.  
  404.     dc_iscale = abs(vis->xiscale)>>detailshift;
  405.     dc_texturemid = vis->texturemid;
  406.     frac = vis->startfrac;
  407.     spryscale = vis->scale;
  408.  
  409.     sprtopscreen = centeryfrac - FixedMul(dc_texturemid,spryscale);
  410.  
  411.     // check to see if vissprite is a weapon
  412.     if(vis->psprite)
  413.     {
  414.         dc_texturemid += FixedMul(((centery-viewheight/2)<<FRACBITS),
  415.             vis->xiscale);
  416.         sprtopscreen += (viewheight/2-centery)<<FRACBITS;
  417.     }
  418.  
  419.     if(vis->floorclip && !vis->psprite)
  420.     {
  421.         sprbotscreen = sprtopscreen+FixedMul(patch->height<<FRACBITS,
  422.             spryscale);
  423.         baseclip = (sprbotscreen-FixedMul(vis->floorclip, 
  424.             spryscale))>>FRACBITS;
  425.     }
  426.     else
  427.     {
  428.         baseclip = -1;
  429.     }
  430.  
  431.     for (dc_x=vis->x1 ; dc_x<=vis->x2 ; dc_x++, frac += vis->xiscale)
  432.     {
  433.         texturecolumn = frac>>FRACBITS;
  434. #ifdef RANGECHECK
  435.         if (texturecolumn < 0 || texturecolumn >= SHORT(patch->width))
  436.             I_Error ("R_DrawSpriteRange: bad texturecolumn");
  437. #endif
  438.         column = (column_t *) ((byte *)patch +
  439.          LONG(patch->columnofs[texturecolumn]));
  440.          R_DrawMaskedColumn (column, baseclip);
  441.     }
  442.  
  443.     colfunc = basecolfunc;
  444. }
  445.  
  446.  
  447.  
  448. /*
  449. ===================
  450. =
  451. = R_ProjectSprite
  452. =
  453. = Generates a vissprite for a thing if it might be visible
  454. =
  455. ===================
  456. */
  457.  
  458. void R_ProjectSprite (mobj_t *thing)
  459. {
  460.     fixed_t        trx,try;
  461.     fixed_t        gxt,gyt;
  462.     fixed_t        tx,tz;
  463.     fixed_t        xscale;
  464.     int            x1, x2;
  465.     spritedef_t    *sprdef;
  466.     spriteframe_t    *sprframe;
  467.     int            lump;
  468.     unsigned    rot;
  469.     boolean        flip;
  470.     int            index;
  471.     vissprite_t    *vis;
  472.     angle_t        ang;
  473.     fixed_t        iscale;
  474.  
  475.     if(thing->flags2&MF2_DONTDRAW)
  476.     { // Never make a vissprite when MF2_DONTDRAW is flagged.
  477.         return;
  478.     }
  479.  
  480. //
  481. // transform the origin point
  482. //
  483.     trx = thing->x - viewx;
  484.     try = thing->y - viewy;
  485.  
  486.     gxt = FixedMul(trx,viewcos);
  487.     gyt = -FixedMul(try,viewsin);
  488.     tz = gxt-gyt;
  489.  
  490.     if (tz < MINZ)
  491.         return;        // thing is behind view plane
  492.     xscale = FixedDiv(projection, tz);
  493.  
  494.     gxt = -FixedMul(trx,viewsin);
  495.     gyt = FixedMul(try,viewcos);
  496.     tx = -(gyt+gxt);
  497.     
  498.     if (abs(tx)>(tz<<2))
  499.         return;        // too far off the side
  500.  
  501. //
  502. // decide which patch to use for sprite reletive to player
  503. //
  504. #ifdef RANGECHECK
  505.     if ((unsigned)thing->sprite >= numsprites)
  506.         I_Error ("R_ProjectSprite: invalid sprite number %i ",thing->sprite);
  507. #endif
  508.     sprdef = &sprites[thing->sprite];
  509. #ifdef RANGECHECK
  510.     if ( (thing->frame&FF_FRAMEMASK) >= sprdef->numframes )
  511.         I_Error ("R_ProjectSprite: invalid sprite frame %i : %i "
  512.         ,thing->sprite, thing->frame);
  513. #endif
  514.     sprframe = &sprdef->spriteframes[ thing->frame & FF_FRAMEMASK];
  515.  
  516.     if (sprframe->rotate)
  517.     {    // choose a different rotation based on player view
  518.         ang = R_PointToAngle (thing->x, thing->y);
  519.         rot = (ang-thing->angle+(unsigned)(ANG45/2)*9)>>29;
  520.         lump = sprframe->lump[rot];
  521.         flip = (boolean)sprframe->flip[rot];
  522.     }
  523.     else
  524.     {    // use single rotation for all views
  525.         lump = sprframe->lump[0];
  526.         flip = (boolean)sprframe->flip[0];
  527.     }
  528.  
  529. //
  530. // calculate edges of the shape
  531. //
  532.     tx -= spriteoffset[lump];
  533.     x1 = (centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS;
  534.     if (x1 > viewwidth)
  535.         return;        // off the right side
  536.     tx +=  spritewidth[lump];
  537.     x2 = ((centerxfrac + FixedMul (tx,xscale) ) >>FRACBITS) - 1;
  538.     if (x2 < 0)
  539.         return;        // off the left side
  540.  
  541.  
  542. //
  543. // store information in a vissprite
  544. //
  545.     vis = R_NewVisSprite ();
  546.     vis->mobjflags = thing->flags;
  547.     vis->psprite = false;
  548.     vis->scale = xscale<<detailshift;
  549.     vis->gx = thing->x;
  550.     vis->gy = thing->y;
  551.     vis->gz = thing->z;
  552.     vis->gzt = thing->z + spritetopoffset[lump];
  553.     if(thing->flags&MF_TRANSLATION)
  554.     {
  555.         if(thing->player)
  556.         {
  557.             vis->class = thing->player->class;
  558.         }
  559.         else
  560.         {
  561.             vis->class = thing->special1;
  562.         }
  563.         if(vis->class > 2)
  564.         {
  565.             vis->class = 0;
  566.         }
  567.     }
  568.     // foot clipping
  569.     vis->floorclip = thing->floorclip;
  570.     vis->texturemid = vis->gzt-viewz-vis->floorclip;
  571.  
  572.     vis->x1 = x1 < 0 ? 0 : x1;
  573.     vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
  574.     iscale = FixedDiv (FRACUNIT, xscale);
  575.     if (flip)
  576.     {
  577.         vis->startfrac = spritewidth[lump]-1;
  578.         vis->xiscale = -iscale;
  579.     }
  580.     else
  581.     {
  582.         vis->startfrac = 0;
  583.         vis->xiscale = iscale;
  584.     }
  585.     if (vis->x1 > x1)
  586.         vis->startfrac += vis->xiscale*(vis->x1-x1);
  587.     vis->patch = lump;
  588. //
  589. // get light level
  590. //
  591.  
  592. //    if (thing->flags & MF_SHADOW)
  593. //        vis->colormap = NULL;            // shadow draw
  594. //    else ...
  595.  
  596.     if (fixedcolormap)
  597.         vis->colormap = fixedcolormap;    // fixed map
  598.     else if(LevelUseFullBright && thing->frame&FF_FULLBRIGHT)
  599.         vis->colormap = colormaps;        // full bright
  600.     else
  601.     {                                    // diminished light
  602.         index = xscale>>(LIGHTSCALESHIFT-detailshift);
  603.         if (index >= MAXLIGHTSCALE)
  604.             index = MAXLIGHTSCALE-1;
  605.         vis->colormap = spritelights[index];
  606.     }
  607. }
  608.  
  609.  
  610.  
  611.  
  612. /*
  613. ========================
  614. =
  615. = R_AddSprites
  616. =
  617. ========================
  618. */
  619.  
  620. void R_AddSprites (sector_t *sec)
  621. {
  622.     mobj_t        *thing;
  623.     int            lightnum;
  624.  
  625.     if (sec->validcount == validcount)
  626.         return;        // already added
  627.  
  628.     sec->validcount = validcount;
  629.  
  630.     lightnum = (sec->lightlevel >> LIGHTSEGSHIFT)+extralight;
  631.     if (lightnum < 0)
  632.         spritelights = scalelight[0];
  633.     else if (lightnum >= LIGHTLEVELS)
  634.         spritelights = scalelight[LIGHTLEVELS-1];
  635.     else
  636.         spritelights = scalelight[lightnum];
  637.  
  638.  
  639.     for (thing = sec->thinglist ; thing ; thing = thing->snext)
  640.         R_ProjectSprite (thing);
  641. }
  642.  
  643.  
  644. /*
  645. ========================
  646. =
  647. = R_DrawPSprite
  648. =
  649. ========================
  650. */
  651.  
  652. // Y-adjustment values for full screen (4 weapons)
  653. int PSpriteSY[NUMCLASSES][NUMWEAPONS] =
  654. {
  655.     { 0, -12*FRACUNIT, -10*FRACUNIT, 10*FRACUNIT }, // Fighter
  656.     { -8*FRACUNIT, 10*FRACUNIT, 10*FRACUNIT, 0 }, // Cleric
  657.     { 9*FRACUNIT, 20*FRACUNIT, 20*FRACUNIT, 20*FRACUNIT }, // Mage 
  658.     { 10*FRACUNIT, 10*FRACUNIT, 10*FRACUNIT, 10*FRACUNIT } // Pig
  659. };
  660.  
  661. void R_DrawPSprite (pspdef_t *psp)
  662. {
  663.     fixed_t        tx;
  664.     int            x1, x2;
  665.     spritedef_t    *sprdef;
  666.     spriteframe_t    *sprframe;
  667.     int            lump;
  668.     boolean        flip;
  669.     vissprite_t    *vis, avis;
  670.  
  671.     int tempangle;
  672.  
  673. //
  674. // decide which patch to use
  675. //
  676. #ifdef RANGECHECK
  677.     if ( (unsigned)psp->state->sprite >= numsprites)
  678.         I_Error ("R_ProjectSprite: invalid sprite number %i "
  679.         , psp->state->sprite);
  680. #endif
  681.     sprdef = &sprites[psp->state->sprite];
  682. #ifdef RANGECHECK
  683.     if ( (psp->state->frame & FF_FRAMEMASK)  >= sprdef->numframes)
  684.         I_Error ("R_ProjectSprite: invalid sprite frame %i : %i "
  685.         , psp->state->sprite, psp->state->frame);
  686. #endif
  687.     sprframe = &sprdef->spriteframes[ psp->state->frame & FF_FRAMEMASK ];
  688.  
  689.     lump = sprframe->lump[0];
  690.     flip = (boolean)sprframe->flip[0];
  691.  
  692. //
  693. // calculate edges of the shape
  694. //
  695.     tx = psp->sx-160*FRACUNIT;
  696.  
  697.     tx -= spriteoffset[lump];
  698.     if(viewangleoffset)
  699.     {
  700.         tempangle = ((centerxfrac/1024)*(viewangleoffset>>ANGLETOFINESHIFT));
  701.     }
  702.     else
  703.     {
  704.         tempangle = 0;
  705.     }
  706.     x1 = (centerxfrac + FixedMul (tx,pspritescale)+tempangle ) >>FRACBITS;
  707.     if (x1 > viewwidth)
  708.         return;        // off the right side
  709.     tx +=  spritewidth[lump];
  710.     x2 = ((centerxfrac + FixedMul (tx, pspritescale)+tempangle ) >>FRACBITS) - 1;
  711.     if (x2 < 0)
  712.         return;        // off the left side
  713.  
  714. //
  715. // store information in a vissprite
  716. //
  717.     vis = &avis;
  718.     vis->mobjflags = 0;
  719.     vis->class = 0;
  720.     vis->psprite = true;
  721.     vis->texturemid = (BASEYCENTER<<FRACBITS)+FRACUNIT/2
  722.         -(psp->sy-spritetopoffset[lump]);
  723.     if(viewheight == SCREENHEIGHT)
  724.     {
  725.         vis->texturemid -= PSpriteSY[viewplayer->class]
  726.             [players[consoleplayer].readyweapon];
  727.     }
  728.     vis->x1 = x1 < 0 ? 0 : x1;
  729.     vis->x2 = x2 >= viewwidth ? viewwidth-1 : x2;
  730.     vis->scale = pspritescale<<detailshift;
  731.     if (flip)
  732.     {
  733.         vis->xiscale = -pspriteiscale;
  734.         vis->startfrac = spritewidth[lump]-1;
  735.     }
  736.     else
  737.     {
  738.         vis->xiscale = pspriteiscale;
  739.         vis->startfrac = 0;
  740.     }
  741.     if (vis->x1 > x1)
  742.         vis->startfrac += vis->xiscale*(vis->x1-x1);
  743.     vis->patch = lump;
  744.  
  745.     if(viewplayer->powers[pw_invulnerability] && viewplayer->class
  746.         == PCLASS_CLERIC)
  747.     {
  748.         vis->colormap = spritelights[MAXLIGHTSCALE-1];
  749.         if(viewplayer->powers[pw_invulnerability] > 4*32)
  750.         {
  751.             if(viewplayer->mo->flags2&MF2_DONTDRAW)
  752.             { // don't draw the psprite
  753.                 vis->mobjflags |= MF_SHADOW;
  754.             }
  755.             else if(viewplayer->mo->flags&MF_SHADOW)
  756.             {
  757.                 vis->mobjflags |= MF_ALTSHADOW;
  758.             }
  759.         }
  760.         else if(viewplayer->powers[pw_invulnerability]&8)
  761.         {
  762.             vis->mobjflags |= MF_SHADOW;
  763.         }
  764.     }    
  765.     else if(fixedcolormap)
  766.     {
  767.         // Fixed color
  768.         vis->colormap = fixedcolormap;
  769.     }
  770.     else if(psp->state->frame & FF_FULLBRIGHT)
  771.     {
  772.         // Full bright
  773.         vis->colormap = colormaps;
  774.     }
  775.     else
  776.     {
  777.         // local light
  778.         vis->colormap = spritelights[MAXLIGHTSCALE-1];
  779.     }
  780.     R_DrawVisSprite(vis, vis->x1, vis->x2);
  781. }
  782.  
  783. /*
  784. ========================
  785. =
  786. = R_DrawPlayerSprites
  787. =
  788. ========================
  789. */
  790.  
  791. void R_DrawPlayerSprites (void)
  792. {
  793.     int            i, lightnum;
  794.     pspdef_t    *psp;
  795.  
  796. //
  797. // get light level
  798. //
  799.     lightnum = (viewplayer->mo->subsector->sector->lightlevel >> LIGHTSEGSHIFT)
  800.         +extralight;
  801.     if (lightnum < 0)
  802.         spritelights = scalelight[0];
  803.     else if (lightnum >= LIGHTLEVELS)
  804.         spritelights = scalelight[LIGHTLEVELS-1];
  805.     else
  806.         spritelights = scalelight[lightnum];
  807. //
  808. // clip to screen bounds
  809. //
  810.     mfloorclip = screenheightarray;
  811.     mceilingclip = negonearray;
  812.  
  813. //
  814. // add all active psprites
  815. //
  816.     for (i=0, psp=viewplayer->psprites ; i<NUMPSPRITES ; i++,psp++)
  817.         if (psp->state)
  818.             R_DrawPSprite (psp);
  819.  
  820. }
  821.  
  822.  
  823. /*
  824. ========================
  825. =
  826. = R_SortVisSprites
  827. =
  828. ========================
  829. */
  830.  
  831. vissprite_t    vsprsortedhead;
  832.  
  833. void R_SortVisSprites (void)
  834. {
  835.     int            i, count;
  836.     vissprite_t    *ds, *best;
  837.     vissprite_t    unsorted;
  838.     fixed_t        bestscale;
  839.  
  840.     count = vissprite_p - vissprites;
  841.  
  842.     unsorted.next = unsorted.prev = &unsorted;
  843.     if (!count)
  844.         return;
  845.  
  846.     for (ds=vissprites ; ds<vissprite_p ; ds++)
  847.     {
  848.         ds->next = ds+1;
  849.         ds->prev = ds-1;
  850.     }
  851.     vissprites[0].prev = &unsorted;
  852.     unsorted.next = &vissprites[0];
  853.     (vissprite_p-1)->next = &unsorted;
  854.     unsorted.prev = vissprite_p-1;
  855.  
  856. //
  857. // pull the vissprites out by scale
  858. //
  859.     best = 0;        // shut up the compiler warning
  860.     vsprsortedhead.next = vsprsortedhead.prev = &vsprsortedhead;
  861.     for (i=0 ; i<count ; i++)
  862.     {
  863.         bestscale = MAXINT;
  864.         for (ds=unsorted.next ; ds!= &unsorted ; ds=ds->next)
  865.         {
  866.             if (ds->scale < bestscale)
  867.             {
  868.                 bestscale = ds->scale;
  869.                 best = ds;
  870.             }
  871.         }
  872.         best->next->prev = best->prev;
  873.         best->prev->next = best->next;
  874.         best->next = &vsprsortedhead;
  875.         best->prev = vsprsortedhead.prev;
  876.         vsprsortedhead.prev->next = best;
  877.         vsprsortedhead.prev = best;
  878.     }
  879. }
  880.  
  881.  
  882.  
  883. /*
  884. ========================
  885. =
  886. = R_DrawSprite
  887. =
  888. ========================
  889. */
  890.  
  891. void R_DrawSprite (vissprite_t *spr)
  892. {
  893.     drawseg_t        *ds;
  894.     short            clipbot[SCREENWIDTH], cliptop[SCREENWIDTH];
  895.     int                x, r1, r2;
  896.     fixed_t            scale, lowscale;
  897.     int                silhouette;
  898.  
  899.     for (x = spr->x1 ; x<=spr->x2 ; x++)
  900.         clipbot[x] = cliptop[x] = -2;
  901.  
  902. //
  903. // scan drawsegs from end to start for obscuring segs
  904. // the first drawseg that has a greater scale is the clip seg
  905. //
  906.     for (ds=ds_p-1 ; ds >= drawsegs ; ds--)
  907.     {
  908.         //
  909.         // determine if the drawseg obscures the sprite
  910.         //
  911.         if (ds->x1 > spr->x2 || ds->x2 < spr->x1 ||
  912.         (!ds->silhouette && !ds->maskedtexturecol) )
  913.             continue;            // doesn't cover sprite
  914.  
  915.         r1 = ds->x1 < spr->x1 ? spr->x1 : ds->x1;
  916.         r2 = ds->x2 > spr->x2 ? spr->x2 : ds->x2;
  917.         if (ds->scale1 > ds->scale2)
  918.         {
  919.             lowscale = ds->scale2;
  920.             scale = ds->scale1;
  921.         }
  922.         else
  923.         {
  924.             lowscale = ds->scale1;
  925.             scale = ds->scale2;
  926.         }
  927.  
  928.         if (scale < spr->scale || ( lowscale < spr->scale
  929.         && !R_PointOnSegSide (spr->gx, spr->gy, ds->curline) ) )
  930.         {
  931.             if (ds->maskedtexturecol)    // masked mid texture
  932.                 R_RenderMaskedSegRange (ds, r1, r2);
  933.             continue;            // seg is behind sprite
  934.         }
  935.  
  936. //
  937. // clip this piece of the sprite
  938. //
  939.         silhouette = ds->silhouette;
  940.         if (spr->gz >= ds->bsilheight)
  941.             silhouette &= ~SIL_BOTTOM;
  942.         if (spr->gzt <= ds->tsilheight)
  943.             silhouette &= ~SIL_TOP;
  944.  
  945.         if (silhouette == 1)
  946.         {    // bottom sil
  947.             for (x=r1 ; x<=r2 ; x++)
  948.                 if (clipbot[x] == -2)
  949.                     clipbot[x] = ds->sprbottomclip[x];
  950.         }
  951.         else if (silhouette == 2)
  952.         {    // top sil
  953.             for (x=r1 ; x<=r2 ; x++)
  954.                 if (cliptop[x] == -2)
  955.                     cliptop[x] = ds->sprtopclip[x];
  956.         }
  957.         else if (silhouette == 3)
  958.         {    // both
  959.             for (x=r1 ; x<=r2 ; x++)
  960.             {
  961.                 if (clipbot[x] == -2)
  962.                     clipbot[x] = ds->sprbottomclip[x];
  963.                 if (cliptop[x] == -2)
  964.                     cliptop[x] = ds->sprtopclip[x];
  965.             }
  966.         }
  967.  
  968.     }
  969.  
  970. //
  971. // all clipping has been performed, so draw the sprite
  972. //
  973.  
  974. // check for unclipped columns
  975.     for (x = spr->x1 ; x<=spr->x2 ; x++)
  976.     {
  977.         if (clipbot[x] == -2)
  978.             clipbot[x] = viewheight;
  979.         if (cliptop[x] == -2)
  980.             cliptop[x] = -1;
  981.     }
  982.  
  983.     mfloorclip = clipbot;
  984.     mceilingclip = cliptop;
  985.     R_DrawVisSprite (spr, spr->x1, spr->x2);
  986. }
  987.  
  988.  
  989. /*
  990. ========================
  991. =
  992. = R_DrawMasked
  993. =
  994. ========================
  995. */
  996.  
  997. void R_DrawMasked (void)
  998. {
  999.     vissprite_t        *spr;
  1000.     drawseg_t        *ds;
  1001.  
  1002.     R_SortVisSprites ();
  1003.  
  1004.     if (vissprite_p > vissprites)
  1005.     {
  1006.     // draw all vissprites back to front
  1007.  
  1008.         for (spr = vsprsortedhead.next ; spr != &vsprsortedhead
  1009.         ; spr=spr->next)
  1010.             R_DrawSprite (spr);
  1011.     }
  1012.  
  1013. //
  1014. // render any remaining masked mid textures
  1015. //
  1016.     for (ds=ds_p-1 ; ds >= drawsegs ; ds--)
  1017.         if (ds->maskedtexturecol)
  1018.             R_RenderMaskedSegRange (ds, ds->x1, ds->x2);
  1019.  
  1020. //
  1021. // draw the psprites on top of everything
  1022. //
  1023. // Added for the sideviewing with an external device
  1024.     if (viewangleoffset <= 1024<<ANGLETOFINESHIFT || viewangleoffset >=
  1025.             -1024<<ANGLETOFINESHIFT)
  1026.       {    // don't draw on side views
  1027.         R_DrawPlayerSprites ();
  1028.     }
  1029.  
  1030. //    if (!viewangleoffset)        // don't draw on side views
  1031. //        R_DrawPlayerSprites ();
  1032. }
  1033.  
  1034.  
  1035.